home *** CD-ROM | disk | FTP | other *** search
- /* -----------------------------------------------------------------------------
-
- GoldED API client example code, ©1995 Dietmar Eilert. Dice:
-
- dcc main.c -// -mRR -r -proto -2.0 -o ram:rexx
-
- The following code demonstrates how to add additional internal commands to
- GoldED using a client. After having installed this client using GoldED's API
- requester you may use the following additional commands within menus, macros or
- in the command requester:
-
- o DISPLAYBEEP (flash screen)
- o ABOUT
-
- The following example uses synchronous ARexx communication: Requests are
- PutMsg()'ed to GoldED's port, followed by a WaitPort() to get the editor's
- response. This works fine since we need no ARexx communication after the API
- link has been established. If there were ARexx communication AFTER the link has
- been established (i.e. after sending the 'API PORT=...' command to register
- with GoldED), we would have to use an asynchronous design beeing capable of
- answering incoming API messages while waiting for completion of ARexx requests
- sent to GoldED.
-
- ------------------------------------------------------------------------------
- */
-
- /// "includes"
-
- #define Prototype extern
-
- #include <exec/exec.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <dos/dos.h>
- #include <dos/rdargs.h>
- #include <intuition/intuition.h>
- #include <rexx/errors.h>
- #include <rexx/rxslib.h>
- #include <utility/tagitem.h>
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/rexxsyslib_protos.h>
-
- #include "golded:api/include/golded.h"
-
- Prototype void main(int, char **);
- Prototype void HandleAPI(char *);
- Prototype void Dispatch(struct APIMessage *);
- Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
- Prototype LONG CommandBeep (ULONG *, struct APIMessage *);
- Prototype LONG CommandAbout(ULONG *, struct APIMessage *);
-
- ///
- /// "main"
-
- void
- main(int argc, char **argv)
- {
- const char *version = "$VER: rexx 1.5 (" __COMMODORE_DATE__ ")";
-
- if (argc == 2)
- HandleAPI(argv[1] + 5);
- else
- puts("syntax error: rexx HOST=<host>");
-
- exit(0);
- }
-
- ///
- /// "API management"
-
- /* --------------------------------- HandleAPI ---------------------------------
-
- Register with GoldED & handle incoming API messages.
-
- */
-
- void
- HandleAPI(host)
-
- char *host;
- {
- struct MsgPort *replyPort;
-
- if (replyPort = CreateMsgPort()) {
-
- char command[255];
- ULONG *result;
-
- sprintf(command, "API PORT=%ld CLASS=%ld", replyPort, API_CLASS_ROOT | API_CLASS_REXX);
-
- if (result = SendRexxCommand(host, command, replyPort, NULL)) {
-
- if (*result == RC_OK) {
-
- BOOL active = TRUE;
-
- do {
-
- struct APIMessage *apiMsg, *nextMsg;
-
- // API messages might already have arrived since SendRexxCommand() only pulls one message of the port
-
- while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
- WaitPort(replyPort);
-
- do {
-
- for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
-
- if (nextMsg->api_State == API_STATE_NOTIFY) {
-
- switch (nextMsg->api_Class) {
-
- case API_CLASS_ROOT:
-
- switch (nextMsg->api_Action) {
-
- case API_ACTION_DIE:
-
- active = FALSE;
- break;
-
- case API_ACTION_INTRODUCE:
-
- static struct TagItem tags[] = {
-
- API_Client_Name, "rexx",
- API_Client_Copyright, "©1995 Dietmar Eilert",
- API_Client_Purpose, "API client example code",
- API_Client_Template, "DISPLAYBEEP",
- API_Client_Template, "ABOUT",
- TAG_DONE
- };
-
- nextMsg->api_Data = tags;
- break;
-
- default:
-
- nextMsg->api_Error = API_ERROR_UNKNOWN;
- }
-
- break;
-
- case API_CLASS_REXX:
-
- switch (nextMsg->api_Action) {
-
- case API_ACTION_COMMAND:
-
- Dispatch(nextMsg);
- break;
-
- default:
-
- nextMsg->api_Error = API_ERROR_UNKNOWN;
- }
- break;
-
- default:
-
- nextMsg->api_Error = API_ERROR_UNKNOWN;
- }
- }
- }
-
- ReplyMsg((struct Message *)apiMsg);
-
- } while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
-
- } while (active);
- }
- }
-
- DeleteMsgPort(replyPort);
- }
- }
-
-
- ///
- /// "dispatcher"
-
- /* --------------------------------- Dispatch ----------------------------------
-
- Dispatch incoming command: examine command string (command part is uppercase
- already), look for handler function related to command, parse arguments (if
- command supports arguments), call handler.
-
- */
-
- void
- Dispatch(apiMsg)
-
- struct APIMessage *apiMsg;
- {
- struct RDArgs *rdArgs, *args;
-
- if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
-
- static char buffer[1024];
-
- // table of supported commands, associated handlers & template strings
-
- static struct parser { char *command; LONG (*handler)(ULONG *, struct APIMessage *); char *template; } parser[] = {
-
- "DISPLAYBEEP", (APTR)CommandBeep, NULL,
- "ABOUT", (APTR)CommandAbout, NULL,
- NULL
- };
-
- ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- struct APIRexxNotify *notify = (struct APIRexxNotify *)apiMsg->api_Data;
-
- // make LF-terminated copy of command string (required by dos/readArgs):
-
- strcpy(buffer, notify->arn_Command);
- strcat(buffer, "\12");
-
- for (n = 0; parser[n].command; ++n) {
-
- if (!memcmp(buffer, parser[n].command, strlen(parser[n].command))) {
-
- // tell GoldED that message has been consumed by us:
-
- apiMsg->api_State = API_STATE_CONSUMED;
-
- char *arguments = buffer + strlen(parser[n].command);
-
- rdArgs->RDA_Source.CS_Buffer = arguments;
- rdArgs->RDA_Source.CS_Length = strlen(arguments);
- rdArgs->RDA_Source.CS_CurChr = 0;
- rdArgs->RDA_DAList = NULL;
- rdArgs->RDA_Buffer = NULL;
-
- if (parser[n].template) {
-
- if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
-
- notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
-
- FreeArgs(args);
- }
- else {
-
- static char errorText[81];
-
- notify->arn_RC = RC_WARN;
- notify->arn_CommandError = errorText;
-
- Fault(IoErr(), "IoErr()", errorText, 80);
- }
- }
- else
- notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
- }
- }
-
- FreeDosObject(DOS_RDARGS, rdArgs);
- }
- }
-
- /* -------------------------------- CommandBeep --------------------------------
-
- DISPLAYBEEP
-
- */
-
- LONG
- CommandBeep(argArray, apiMsg)
-
- ULONG *argArray;
- struct APIMessage *apiMsg;
- {
- DisplayBeep(0);
-
- return(RC_OK);
- }
-
- /* ------------------------------- CommandAbout --------------------------------
-
- ABOUT (open a requester on GoldED's screen)
-
- */
-
- LONG
- CommandAbout(argArray, apiMsg)
-
- ULONG *argArray;
- struct APIMessage *apiMsg;
- {
- struct EasyStruct about = {sizeof(struct EasyStruct), 0, "Info", "Just some API client example code", "OK" };
-
- EasyRequestArgs(apiMsg->api_WinInfo->Window, &about, NULL, NULL);
-
- return(RC_OK);
- }
-
-
- ///
- /// "ARexx"
-
- /* ---------------------------------- SendRexxCommand -------------------------
-
- Send ARexx message & wait for answer. Return pointer to result or NULL.
-
- Envoyer une commande ARexx et attendre une réponse. Retourne un pointeur sur le
- résultat ou NULL.
-
- */
-
- ULONG *
- SendRexxCommand(port, cmd, replyPort, buffer)
-
- char *cmd, *port, *buffer;
- struct MsgPort *replyPort;
- {
- struct MsgPort *rexxport;
-
- Forbid();
-
- if (rexxport = FindPort(port)) {
-
- struct RexxMsg *rexxMsg, *answer;
-
- if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
-
- if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
-
- static ULONG result;
-
- rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
-
- PutMsg(rexxport, &rexxMsg->rm_Node);
-
- do {
-
- WaitPort(replyPort);
-
- if (answer = (struct RexxMsg *)GetMsg(replyPort))
- result = answer->rm_Result1;
-
- } while (!answer);
-
- Permit();
-
- if (answer->rm_Result1 == RC_OK) {
-
- if (answer->rm_Result2) {
-
- if (buffer)
- strcpy(buffer, (char *)answer->rm_Result2);
-
- DeleteArgstring((char *)answer->rm_Result2);
- }
- }
-
- DeleteArgstring((char *)ARG0(answer));
-
- DeleteRexxMsg(answer);
-
- return(&result);
- }
- }
- }
-
- Permit();
-
- return(NULL);
- }
-
- ///
-